#!/usr/bin/python

import subprocess as sp 
from sys import argv, stdout, exit

def test_think_time(proccount, nodesize, heapsize, deletes, inserts, outfile, pf_outfile):
    ''' runs sequential heap and parallel heap with increasing 
        thinktime values
    '''
    Header2 = "GPs\MPs,"
    for i in range(proccount):
          Header2 = Header2 + "," + str(i)

                
    cycles =  256

    outfile.write( 'Graph for SpeedUp Vs Different Think Time Values for heapRR')
    pf_outfile.write( 'Graph for SpeedUp Vs Different Think Time Values for heapRR')
    MinTime   = 10000000.0
    MinTimePF = 10000000.0
    outfile.write    (Header2);
    pf_outfile.write    (Header2);
    for t in range(1, 6002, 1000):
                index = 0;
                Timing    = []
                TimingPF  = []
                Filler    = []
                for i in range(proccount):
                    Filler.append(" ")
                SeqTime = heapSeq(1, heapsize, deletes, inserts, t,  cycles)
                SeqTiming = float(SeqTime)
                for mprocs in range(1, proccount+1):
                    ParTime   = heapRR(proccount, nodesize, heapsize, cycles, t, deletes, inserts,  mprocs)
                    ParPFTime = heapRRPF(proccount, nodesize, heapsize, cycles, t, deletes, inserts,  mprocs)
                    
                    Timing.append(float(ParTime))
                    TimingPF.append(float(ParPFTime))
                    Filler.remove(Filler[0])

                    if (Timing  [index] < MinTime ): MinTime   = Timing[index]
                    if (TimingPF[index] < MinTime ): MinTimePF = TimingPF[index]

                    index = index + 1
                outfile.write    (SeqTime + "\n" + str(Timing)   + str(Filler) + str(MinTime) + "," + str(SeqTiming/MinTime)   + "\n")
                pf_outfile.write (SeqTime + "\n" + str(TimingPF) + str(Filler) + str(MinTimePF) + "," + str(SeqTiming/MinTimePF) + "\n")

    outfile.write( 'Graph for SpeedUp Vs Different Think Time Values for heapPar')
    pf_outfile.write( 'Graph for SpeedUp Vs Different Think Time Values for heapPar')
    MinTime   = 10000000.0
    MinTimePF = 10000000.0
    outfile.write    (Header2);
    pf_outfile.write    (Header2);
    for t in range(1, 6002, 1000):
                index = 0;
                row   = 1;
                Timing    = []
                TimingPF  = []
                Filler    = []
                for i in range(proccount):
                    Filler.append(" ")
           
                SeqTime = heapSeq(1, heapsize, deletes, inserts, t,  cycles)
                SeqTiming = float(SeqTime)
                for mprocs in range(1, proccount+1):
                    ParTime   = heapPar(proccount, nodesize, heapsize, cycles, t, deletes, inserts,  mprocs)
                    ParPFTime = heapParPF(proccount, nodesize, heapsize, cycles, t, deletes, inserts,  mprocs)
                    Timing.append(float(ParTime))
                    TimingPF.append(float(ParPFTime))
                    Filler.remove(Filler[0])

                    if (Timing  [index] < MinTime ): MinTime   = Timing[index]
                    if (TimingPF[index] < MinTime ): MinTimePF = TimingPF[index]

                    index = index + 1
                Header  = "thinkTime = " + str(t) + "\n"
                outfile.write    (Header);
                pf_outfile.write    (Header);
                outfile.write    (str(row) + "," + SeqTime + "\n" + str(Timing)   + str(Filler)  + str(MinTime) + "," + str(SeqTiming/MinTime)   + "\n")
                pf_outfile.write (str(row) + "," + SeqTime + "\n" + str(TimingPF) + str(Filler)  + str(MinTimePF) + "," + str(SeqTiming/MinTimePF) + "\n")
                row = row + 1
    outfile.write( 'Graph for SpeedUp Vs Different Think Time Values for heapBLOCK')
    pf_outfile.write( 'Graph for SpeedUp Vs Different Think Time Values for heapBLOCKPF')
    MinTime   = 10000000.0
    MinTimePF = 10000000.0
    outfile.write    (Header2);
    pf_outfile.write    (Header2);
    for t in range(1, 6002, 1000):
                index = 0;
                Timing    = []
                TimingPF  = []
                Filler    = []
                for i in range(proccount):
                    Filler.append(" ")
                SeqTime = heapSeq(1, heapsize, deletes, inserts, t,  cycles)
                SeqTiming = float(SeqTime)
                for mprocs in range(1,proccount+1):
                    ParTime   = heapBLOCK(proccount, nodesize, heapsize, cycles, t, deletes, inserts,  mprocs)
                    ParPFTime = heapBLOCKPF(proccount, nodesize, heapsize, cycles, t, deletes, inserts,  mprocs)
                    Timing.append(float(ParTime))
                    TimingPF.append(float(ParPFTime))
                    Filler.remove(Filler[0])

                    if (Timing  [index] < MinTime ): MinTime   = Timing[index]
                    if (TimingPF[index] < MinTime ): MinTimePF = TimingPF[index]

                    index = index + 1
                outfile.write    (SeqTime + "\n" + str(Timing)  + str(Filler) + str(MinTime) + "," + str(SeqTiming/MinTime)   + "\n")
                pf_outfile.write (SeqTime + "\n" + str(TimingPF) + str(Filler) + str(MinTimePF) + "," + str(SeqTiming/MinTimePF) + "\n")
                    


def test_varying_r(proccount, nodesize, heapsize, thinktime, inserts, deletes, outfile, pf_outfile):
    ''' runs parallel heap with increasing values of r
    '''
    nodesize = int(nodesize)
    k = 0
    outfile.write( 'Graph for increasing r Values')
    pf_outfile.write( 'Graph for increasing r Values')
    MinTime   = 10000000.0
    MinTimePF = 10000000.0
    for k in [32,128,512,1024,2048,4096,8192,16384,32768]:   
        for t in [1, 500, 5000, 10000]:
            cycles = (2**21) / k
            SeqTime = heapSeq(1, heapsize, deletes, inserts, t,  cycles)
            SeqTiming = float(SeqTime)
            print "\n----------------------------------\n"
            for gprocs in range(1,proccount+1):
                index = 0;
                Timing    = []
                TimingPF  = []
                Filler    = []
                for i in range(proccount):
                    Filler.append(" ")
                for mprocs in range(1, gprocs + 1):
                    ParTime   = heapBLOCK(gprocs, k, heapsize, cycles, t, k, k,  mprocs)
                    ParPFTime = heapBLOCKPF(gprocs, k, heapsize, cycles, t, k, k,  mprocs)

                    Timing.append(float(ParTime))
                    TimingPF.append(float(ParPFTime))
                    Filler.remove(Filler[0])

                    if (Timing  [index] < MinTime ): MinTime   = Timing[index]
                    if (TimingPF[index] < MinTime ): MinTimePF = TimingPF[index]

                    index = index + 1
                outfile.write    (SeqTime + "\n" + str(Timing) + str(Filler)  + str(MinTime) + "," + str(SeqTiming/MinTime)   + "\n")
                pf_outfile.write (SeqTime + "\n" + str(TimingPF) + str(Filler) + str(MinTimePF) + "," + str(SeqTiming/MinTimePF) + "\n")

def test_varying_n(proc, outfile, pf_outfile):
    ''' runs parallel heap with increasing values of n
    '''
    nodesize = 8192
    #cycles = 256
    cycles = 2
    t = 5000
    outfile.write   ('Graph for increasing n Values')
    pf_outfile.write('Graph for increasing n Values')
    for heapsize in [262144, 524288, 1024576, 2097152, 4194304, 8388608, 16777216, 33554432]:   
        SeqTime = heapSeq(1, heapsize, deletes, inserts, t,  cycles)
        SeqTiming = float(SeqTime)
        print "\n----------------------------------\n"
        for gprocs in range (1, proc+1):
            MinTime   = 10000000.0
            MinTimePF = 10000000.0
            index = 0;
            Timing    = []
            TimingPF  = []
            Filler    = []
            for i in range(proc):
                Filler.append(" ")
            for mprocs in range(1, gprocs + 1):
                ParTime   = heapPar(gprocs, nodesize, heapsize, cycles, t, nodesize, nodesize,  mprocs)
                ParPFTime = heapParPF(gprocs, nodesize, heapsize, cycles, t, nodesize, nodesize,  mprocs)

                Timing.append(float(ParTime))
                TimingPF.append(float(ParPFTime))
                Filler.remove(Filler[0])

                if (Timing  [index] < MinTime ): MinTime   = Timing[index]
                if (TimingPF[index] < MinTime ): MinTimePF = TimingPF[index]

                index = index + 1
            outfile.write    (SeqTime + "\n" + str(Timing)  + str(Filler) + str(MinTime) + "," + str(SeqTiming/MinTime)   + "\n")
            pf_outfile.write (SeqTime + "\n" + str(TimingPF)+ str(Filler) + str(MinTimePF) + "," + str(SeqTiming/MinTimePF) + "\n")


def heapSeq(processors, heapsize, deletes, inserts, thinktime, cycles):
    ''' this is our wrapper for the sequential heap program
    '''
    process = sp.Popen(['./heapSeq', str(processors), str(heapsize), str(deletes), str(inserts), str(thinktime), str(cycles)], stdout=sp.PIPE)
    sout,serr = process.communicate()
    return sout
def heapPar(processors, nodesize, heapsize, cycles, thinktime, deletes, inserts, mprocessors):
    ''' this is our wrapper for the parallel heap program
    '''
    process = sp.Popen(['./heap', str(processors), str(nodesize), str(heapsize),str(cycles), str(thinktime), str(deletes), str(inserts), str(mprocessors)],stdout = sp.PIPE)
    sout,serr = process.communicate()
    return sout

def heapParPF(processors, nodesize, heapsize, cycles, thinktime, deletes, inserts, mprocessors):
    ''' this is our wrapper for the parallel heap program
    '''
    process = sp.Popen(['./heapPF', str(processors), str(nodesize), str(heapsize),str(cycles), str(thinktime), str(deletes), str(inserts), str(mprocessors)],stdout = sp.PIPE)
    sout,serr = process.communicate()
    return sout

def heapRR(processors, nodesize, heapsize, cycles, thinktime, deletes, inserts, mprocessors):
    ''' this is our wrapper for the parallel heap program
    '''
    process = sp.Popen(['./heapRR', str(processors), str(nodesize), str(heapsize),str(cycles), str(thinktime), str(deletes), str(inserts), str(mprocessors)],stdout = sp.PIPE)
    sout,serr = process.communicate()
    return sout

def heapRRPF(processors, nodesize, heapsize, cycles, thinktime, deletes, inserts, mprocessors):
    ''' this is our wrapper for the parallel heap program
    '''
    process = sp.Popen(['./heapRRPF', str(processors), str(nodesize), str(heapsize),str(cycles), str(thinktime), str(deletes), str(inserts), str(mprocessors)],stdout = sp.PIPE)
    sout,serr = process.communicate()
    return sout

def heapBLOCK(processors, nodesize, heapsize, cycles, thinktime, deletes, inserts, mprocessors):
    ''' this is our wrapper for the parallel heap program
    '''
    process = sp.Popen(['./heapBLOCK', str(processors), str(nodesize), str(heapsize),str(cycles), str(thinktime), str(deletes), str(inserts), str(mprocessors)],stdout = sp.PIPE)
    sout,serr = process.communicate()
    return sout

def heapBLOCKPF(processors, nodesize, heapsize, cycles, thinktime, deletes, inserts, mprocessors):
    ''' this is our wrapper for the parallel heap program
    '''
    process = sp.Popen(['./heapBLOCKPF', str(processors), str(nodesize), str(heapsize),str(cycles), str(thinktime), str(deletes), str(inserts), str(mprocessors)],stdout = sp.PIPE)
    sout,serr = process.communicate()
    return sout

if __name__ == '__main__':

    if len(argv) != 7:
        exit('Usage ./run.py numProc nodeWidth heapSize thinkTime numDeletes numInserts')

    processors  = int(argv[1])
    nodesize    = int(argv[2])
    heapsize    = int(argv[3])
    thinktime   = int(argv[4])
    deletes     = int(argv[5])
    inserts     = int(argv[6])

    outfile = open('./outputfile', 'w')
    pf_outfile = open('./PFoutputfile', 'w')

    test_think_time(processors, nodesize, heapsize, deletes, inserts, outfile, pf_outfile)

    test_varying_r(processors, nodesize, heapsize, thinktime, inserts, deletes, outfile, pf_outfile)

    test_varying_n(processors, outfile, pf_outfile)

